In this lecture, we're going to start finally creating stuff in Roblox.
Specifically in this video, we're going to learn about the tool instance and how we can use it to create
custom tools in our game.
I've created this simple donut model here, and you can grab this model yourself by going to the attached
link in this lecture and adding the model to your inventory.
Once you do that, you can go to the View tab.
Open up the toolbox and go to the inventory tab.
And grab the model from the my model section.
Now we can create a new tool instance and place it in the workspace by pressing this plus button here
and I'll search for a new tool.
And then I can take my donut model here and make it a child of the tool.
The next thing I want to do is remove this model so the tool has direct access to the parts that make
it up.
I can un group these objects by using the combined control.
And you.
The next thing I have to do is rename one of these parts to handle because our tool requires a part
to be identified as a handle.
So the player model knows exactly where to hold the tool at.
So I'll just rename the body of my donut to handle.
We also have to make sure that our tool is unanchored.
Otherwise, if it's anchored, we would not be able to move the character because our hand gets welded
to the donut that's stuck.
One more thing to mention is that since we have two separate parts in our tools that are both unanchored,
we have to weld the extra parts like the icing here to the handle.
That way all the separate parts act as one unit, as one part.
To do this, I can add a weld constraint and make it a child of my icing.
But it doesn't really matter where you parent the weld constraint.
Just know that the first part to the well constraint has to be my icing.
And then the second part is going to be the part I want to weld the icing to.
And in this case, that's the handle.
Now I'll be able to properly hold this doughnut without getting my character stuck.
So we have the shell of our tool created.
Now, how exactly do we script our tool and make it to where I can, I don't know, heal us when we
eat it?
Well, we can create a new local script and make it a child of the tool.
Local scripts specifically run on the client and they do this.
So we're able to know when our player activates our tools, clicks, moves around, presses a certain
key, and so on.
Only local scripts see this and not the server scripts because the server doesn't know exactly what
keys a player is pressing because it's not running on their computer.
So in my local script, I kind of wanted to detect when my player clicks so that way they'll eat the
donut and then I'll heal them with a little bit of health.
I got a first get access to that player.
So to do that, I'm going to create a reference to the player service, which holds all the players
in my game.
This service right here, any time a new client gets added, their player gets put into this service.
And then to get the local player that's executing the script.
I'll create another variable.
I will index the player service and use the local player key value pair to grab the local player.
This will always return the player that is executing the script.
So now that I have access to this player, the other thing I want to access is the tool itself.
So I'll create a variable, call it tool, and then I'll type in the script keyword and the script keyword
refers to this script itself, this script instance.
And then I could do Dot Parent.
And what this does is that this references the parent of my script, which would be the tool, this
tool instance.
Now the tool instance has an event in it called activated.
And this gets fired when a player clicks.
So that's exactly what I want to happen.
When my player clicks, I want them to eat the donut and heal a little bit.
So I'll connect a lambda function to this event.
And then what I could do is I could get my player index the player and get their character, which is
their character model.
And inside their character model they have something called a humanoid.
And this humanoid holds all the properties like health, the players walk speed, all that kind of good
stuff, basically the controller for the character.
And it has a health property that I can access and maybe I want to heal my humanoid by five health so
I can actually do plus equals five.
Now to actually see my player get healed by my tool.
I'm going to go on my game here and I'm going to create a new part.
And this part is going to have a script in it.
And I'll just make sure my part's anchored.
Of course.
And in the script, I'm just going to get a reference to the part by using the same script parent because
this script is a child of the part.
And then I'll access the touched event.
And get the part that touched it.
And I want to see if this part that is touching my part belongs to a character model that has a humanoid
instance in it, which means that it's a player that I can damage.
So I'll create a variable.
I'll call it humanoid.
And it's going to store the result of part parent.
And I'm going to find the first child, which is a humanoid, belongs to the humanoid class.
So what this means is that any ligament that touches my part like a leg, a foot, whatever, if the
parent of it, which should be a character.
And that character has a humanoid instance in it.
That means it's a player so we can damage it.
So create an if statement so if humanoid.
So if this function returns an object doesn't return nil, then I'll damage the humanoid using the take
damage function and I'll put a number in here like ten.
So every time a player touches this part, they get damaged by ten.
Now I'll be able to play my game.
And then touch my part.
Looks like it's not damaging me.
Let's do a little debugging to find out why.
Oh, other part.
We're looking at the part that touched it, not the part itself.
There we go.
Fix that.
That was an example of a logical error, by the way.
Now, if I touch it, it killed me.
That was a little too fast.
Let me just touch it a little bit.
There we go.
I get damaged a lot.
And now if I eat my donut, it should heal me.
There we go.
It's kind of healing me.
This is very odd behavior.
It's not actually healing me.
Why isn't it healing me?
The reason it's not healing me is because I'm running this heal.
I'm change.
I'm trying to alter the health of my humanoid from a local script and that's not going to replicate
to the server and that's not going to replicate to other players.
I need to do this.
I need to perform this statement in a server script.
The way it actually heals me and replicates to all the players.
So how do I do that?
Well, this is where remote events come in.
So in my in my tool, I'll create another script and this is going to be a server script.
And I'm just going to add an event to it, a remote event.
And I'll just call.
It clicked.
In my server script, I'll create a reference to the event and I'll just name it event.
So I'll do script Dot clicked.
Again, script is referring to the script, and since the script has a child name click, I access it
right here.
And then when this event gets fired, I do on server event, I could connect a function to it and I
could get the player that fired the event.
I'm going to go back to my local script and I'm going to create the same variable to the event.
So do script dot parent.
And script parent refers to the tool and then I'll get the server script that is a child of the tool,
and then I'll get the clicked event, which is a child of the script.
And now instead, whenever I activate the tool, I'm not going to heal myself, but instead I'm going
to fire this event using the fire server function.
This function.
I'm telling this event that I want to fire information to the server.
I want to fire this event.
So what happens now is that when this event gets fired, this on server event gets fired, gets activated.
This function executes.
So now I can do player, dot, character, dot humanoid and then get its health.
And set it equal to an extra five health.
Now, if I run my game again, we should be able to properly heal.
So I'll damage myself.
And then there we go.
We aren't having that weird thing we saw earlier.
We're actually healing the character now.
Now, there is one slight problem with this system is that an exploiter can actually sit there and fire
this event super fast, making them heal much faster than we would anticipate them to heal.
So a way around this that we could solve is that in our script and our server script that heals our
player, we can create a variable like last clicked and set it to the result of the function tick.
And what this function does is return the current amount of time in seconds, and then when the player
clicks, when they fire this event, we'll check if the current tick minus when they last clicked,
which will give us the difference in seconds and we'll see if this is greater than or equal to maybe
we want to have like a two second limit and then I'll put it into an if statement.
So that means if the last time they clicked was 2 seconds or greater ago, then we'll heal the player.
So this will stop them from being able to spam Click Healing.
So if I run my game again.
And I go and damage my player a little bit.
And then I try to eat this super fast.
It still works.
Why does it still work?
Oh, forgot one simple thing.
We have to of course.
Update last click to tick.
Right.
Otherwise, if we keep it at the same tick, it'll always be greater than two.
Because the last time we clicked was whenever the script ran.
But if we update it again, then we shouldn't be able to spam click it.
Boom.
Another logical error we just fixed.
Easy peasy.
So I may damage myself again.
Grab my donut.
And then now if I spam click, you see, I'm only being I'm only being healed every 2 seconds.
So this is how you add cooldowns to your scripts.
And you can do the same by adding cool downs to your local script, by creating a variable called D
Bounce.
And it's kind of a special word for cooldown.
So by default, we'll set it to false and we'll check if there is a D bounce.
So basically the cooldown still happening.
Then we'll just exit out of the function.
And then we'll make sure to set d bounce to true.
So that way, if it wasn't true, we set it to true.
And then we fire the event and then we can yield for like 2 seconds.
And then we can set d bounce back to false.
Now, this is just a precaution on the client side, and Exploiter could still easily bypass this.
And just Rapidfire the event, which is why we have this sanity check here on the server to make sure
that they aren't rapid firing the event.
We do it here on the client just in case they can't fire this activated event too often.
Like maybe if our activated event had an animation in it that animated them eating the donut, we don't
want them to spam click and have that animation run over and over again and look all glitchy.
And we'll actually get to make animations for our donut in the next lecture.
I'll see you there.